<template>
    <el-tree node-key="key" ref="treeRef" :props="treeProps" :load="loadNode" lazy show-checkbox
             @check="multipleChecked">
    </el-tree>
</template>

<script setup lang="ts">
import type { TreeData, TreeNode, TreeProps, ElTree } from 'element-ui/types/tree';
import { ref, watch } from 'vue';
import { HouseSelector } from './index.vue';
import { loadNode } from './api'

export interface RoomSelector {
    village: string[],
    stages: string[],
    building: string[],
    unit: string[],
    room: string[]
}

const props = defineProps<{
    value?: HouseSelector,
    disabled?: boolean
}>()


const emit = defineEmits<{
    (event: 'input', value?: HouseSelector): void
}>()

const treeRef = ref<ElTree<string,TreeData>>()
const treeProps: TreeProps = {
    label: 'name',
    disabled: 'isDisabled',
    isLeaf: 'isLeaf',
    children: 'children'
}

function getCheckedNodes() {
    const nodes: TreeData[] = []
    travelTree(node => {
        if (node.checked) {
            nodes.push(node.data)
            return false
        } else if (node.indeterminate) {
            return true
        } else {
            return false
        }
    })
   return nodes
}

/**
 * 深度优先遍历当前树节点，对每个节点调用回调函数
 * @param callback 节点回调函数，返回false以跳过子树，支持异步返回，这种情况下请返回一个Promise, 同时不再保证遍历顺序一致性
 */
function travelTree(callback: (node:TreeNode<string, TreeData>) => boolean | Promise<boolean>) {
    const root = treeRef.value?.root as TreeNode<string, TreeData>
    async function travel(node: TreeNode<string, TreeData>) {
        const deep = callback(node)
        if (typeof deep === 'boolean' && deep || await deep) {
            node.childNodes.forEach(travel)
        }
    }
    return root.childNodes.forEach(travel)
}

watch(() => props.value, async (value, oldValue) => {
    if (value !== oldValue) {
        restoreTreeState()
    }
})

function setExpandedKeys(keys: string[]) {
    travelTree(node => {
        if (keys.includes(node.key)) {
            return new Promise((resolve) => {
                node.expand(() => resolve(true))
            })
        } else {
            node.collapse()
            return false
        }
    })
}


function restoreTreeState() {
    // 赋值给 tree 
    const value = props.value
    let ids: any[] = [];
    if (value) {
        ids.push(...value.village.map(id => 'village:' + id))
        ids.push(...value.stages.map(id => 'stages:' + id))
        ids.push(...value.building.map(id => 'building:' + id))
        ids.push(...value.unit.map(id => 'unit:' + id))
        ids.push(...value.room.map(id => 'room:' + id))
    }
    treeRef.value?.setCheckedKeys(ids);
    if (ids[0]) {
        treeRef.value?.setCurrentKey(ids[0])
    }
}

function multipleChecked() {
    const checkeds = getCheckedNodes()
    console.log(checkeds)
    const input = {
        village: [],
        stages: [],
        building: [],
        unit: [],
        room: []
    }
    checkeds.forEach(node => input[node.type].push(node.id))
    emit('input', input)
}

defineExpose({
    setExpandedKeys
})
</script>

<style scoped>
    .el-tree > :deep( 
    .el-tree-node > .el-tree-node__children > 
    .el-tree-node > .el-tree-node__children > 
    .el-tree-node > .el-tree-node__children > 
    .el-tree-node > .el-tree-node__children) {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        grid-auto-flow: row;
        padding-left: 72px;
    }

    .el-tree > :deep( 
    .el-tree-node > .el-tree-node__children > 
    .el-tree-node > .el-tree-node__children > 
    .el-tree-node > .el-tree-node__children > 
    .el-tree-node > .el-tree-node__children >
    .el-tree-node > .el-tree-node__content) {
        padding-left: 8px !important;
    }
</style>